package com.henghe.frame.core.util;

import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.Objects;

/**
 * Description:
 * Author: LiuWenQing
 * Datetime: 2023/3/27 08:59
 */
public class RedisLock {

    private static final String LOCK_PREFIX = "lock_";
    private static final int LOCK_EXPIRE = 8 * 1000;//ms

    public static boolean lockByNX(String lockKey, RedisTemplate<String,Object> redis) {
        String lock = LOCK_PREFIX + lockKey;
        return Boolean.TRUE.equals(redis.execute((RedisCallback<Boolean>) redisConnection -> {
            String expireAt = String.valueOf(System.currentTimeMillis() + LOCK_EXPIRE + 1);
            {}
            Boolean nx = redisConnection.setNX(lock.getBytes(), expireAt.getBytes());
            if (nx) {
                return true;
            } else {
                byte[] bytes = redisConnection.get(lock.getBytes());
                if (Objects.nonNull(bytes) && bytes.length > 0) {
                    long expireTime = Long.parseLong(new String(bytes));
                    if (expireTime < System.currentTimeMillis()) {
                        byte[] oldValue = redisConnection.getSet(lock.getBytes(), String.valueOf(System.currentTimeMillis() + LOCK_EXPIRE + 1).getBytes());
                        return Long.parseLong(new String(oldValue)) < System.currentTimeMillis();
                    }
                }
            }
            return false;
        }));
    }

    public static void unlockByNX(String lockKey, RedisTemplate redis) {
        String lock = LOCK_PREFIX + lockKey;
        redis.delete(lock);
    }

}
